package com.hna.eking.ZkUtils;

import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.data.Stat;
import org.apache.zookeeper.proto.WatcherEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ZkWatcher implements Watcher {

	public Object mutex;
	private int SESSION_TIMEOUT = 5000; 
	protected String hosts = "127.0.0.1:2181"; 
	private String SessionID;
	private String UUID;
	private String FilePath;
	private ZooKeeper zk;
	private String RootPath = "SynPath";
	private Condition cond;
	private Lock lock;
	
	public final static String PLT_STATUS_RUN  = "0001";
	public final static String PLT_STATUS_SUC  = "0002";
	public final static String PLT_STATUS_FAIL  = "0003";
	
	private static final Logger logger = LoggerFactory.getLogger(ZkWatcher.class);
	
	
	public void process(WatchedEvent evt) {
		// TODO Auto-generated method stub
//		WatcherEvent e = evt.getWrapper();
		
		logger.debug("get watcher:" + evt.getType());
		
		if(evt.getType() !=  Watcher.Event.EventType.NodeDataChanged){
			logger.debug("get watcher===>:" + evt.getType());
			
			return ;
		}
		UnLock();
	}
	public void InitWatcher(){
		try {
			zk = new ZooKeeper(hosts, SESSION_TIMEOUT, this);
			
//			FilePath = String.format("/%s/%s/%s", RootPath, SessionID, UUID);
			FilePath = String.format("/%s", RootPath);
			logger.debug("file:" + FilePath);
			Stat st = zk.exists(FilePath, false);
			if(st == null){
				logger.debug("file " + FilePath + "not exists");
				zk.create(FilePath, PLT_STATUS_RUN.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); 
				FilePath = String.format("/%s/%s", RootPath, SessionID);
				st = zk.exists(FilePath, false);
				if(st == null){
					zk.create(FilePath, PLT_STATUS_RUN.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); 
				}
				FilePath = String.format("/%s/%s/%s", RootPath, SessionID, UUID);
				st = zk.exists(FilePath, false);
				if(st == null){
					zk.create(FilePath, PLT_STATUS_RUN.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); 
				}
			}
			lock = new ReentrantLock();
			cond = lock.newCondition();
		} catch (IOException | KeeperException | InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	
	public void WaitLock(){
		lock.lock();
		logger.debug("Condition locked!");
		try {
			zk.getData(FilePath, this, new Stat());
			cond.await();
			
		} catch (InterruptedException | KeeperException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			logger.debug("Condition await!");
			lock.unlock();
		}
		
		
	}
	
	public void UnLock(){
		lock.lock();
		logger.debug("Condition locked!");
		FilePath = String.format("/%s/%s/%s", RootPath, SessionID, UUID);
//		zk.delete(FilePath, -1);			
		cond.signal();
		logger.debug("Condition signal!");
		lock.unlock();
			
	}
	
	public void CloseWatcher(){
		try {
			
			logger.debug("close watcher ");
	
			FilePath = String.format("/%s/%s/%s", RootPath, SessionID, UUID);
			Stat st = zk.exists(FilePath, false);
			if(st != null){
				zk.delete(FilePath, -1); 
			}
			
			FilePath = String.format("/%s/%s", RootPath, SessionID);
			st = zk.exists(FilePath, false);
			if(st != null){
				zk.delete(FilePath, -1); 
			}
			
			if(zk != null){
				zk.close();
				zk = null;
			}
			
		} catch (InterruptedException | KeeperException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public void CleanSession() {
		try {

			logger.debug("close session ");
			FilePath = String.format("/%s/%s", RootPath, SessionID);
			Stat st = zk.exists(FilePath, false);
			if (st != null) {
				zk.delete(FilePath, -1);
			}
		} catch (InterruptedException | KeeperException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public String getHosts() {
		return hosts;
	}
	public void setHosts(String hosts) {
		this.hosts = hosts;
	}
	public String getSessionID() {
		return SessionID;
	}
	public void setSessionID(String sessionID) {
		SessionID = sessionID;
	}
	public String getUUID() {
		return UUID;
	}
	public void setUUID(String uUID) {
		UUID = uUID;
	}
	public String getRootPath() {
		return RootPath;
	}
	public void setRootPath(String rootPath) {
		RootPath = rootPath;
	}
	
	
}
